home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
Pakiet multimedia
/
Muzyka
/
Edytory sampli (probek dzwieku)
/
ZynAddSubFX_2.2.0
/
Setup_ZynAddSubFX-2.2.0.exe
/
source code
/
Misc
/
Part.C
< prev
next >
Wrap
C/C++ Source or Header
|
2005-03-14
|
25KB
|
876 lines
/*
ZynAddSubFX - a software synthesizer
Part.C - Part implementation
Copyright (C) 2002-2005 Nasca Octavian Paul
Author: Nasca Octavian Paul
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (version 2) for more details.
You should have received a copy of the GNU General Public License (version 2)
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Part.h"
#include "Microtonal.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Part::Part(Microtonal *microtonal_,FFTwrapper *fft_, pthread_mutex_t *mutex_){
microtonal=microtonal_;
fft=fft_;
mutex=mutex_;
partoutl=new REALTYPE [SOUND_BUFFER_SIZE];
partoutr=new REALTYPE [SOUND_BUFFER_SIZE];
tmpoutl=new REALTYPE [SOUND_BUFFER_SIZE];
tmpoutr=new REALTYPE [SOUND_BUFFER_SIZE];
for (int n=0;n<NUM_KIT_ITEMS;n++){
kit[n].Pname=new unsigned char [PART_MAX_NAME_LEN];
kit[n].adpars=NULL;kit[n].subpars=NULL;kit[n].padpars=NULL;
};
kit[0].adpars=new ADnoteParameters(fft);
kit[0].subpars=new SUBnoteParameters();
kit[0].padpars=new PADnoteParameters(fft,mutex);
// ADPartParameters=kit[0].adpars;
// SUBPartParameters=kit[0].subpars;
//Part's Insertion Effects init
for (int nefx=0;nefx<NUM_PART_EFX;nefx++)
partefx[nefx]=new EffectMgr(1,mutex);
for (int n=0;n<NUM_PART_EFX+1;n++) {
partfxinputl[n]=new REALTYPE [SOUND_BUFFER_SIZE];
partfxinputr[n]=new REALTYPE [SOUND_BUFFER_SIZE];
Pefxbypass[n]=false;
};
killallnotes=0;
oldfreq=-1.0;
int i,j;
for (i=0;i<POLIPHONY;i++){
partnote[i].status=KEY_OFF;
partnote[i].note=-1;
partnote[i].itemsplaying=0;
for (j=0;j<NUM_KIT_ITEMS;j++){
partnote[i].kititem[j].adnote=NULL;
partnote[i].kititem[j].subnote=NULL;
partnote[i].kititem[j].padnote=NULL;
};
partnote[i].time=0;
};
cleanup();
Pname=new unsigned char [PART_MAX_NAME_LEN];
oldvolumel=oldvolumer=0.5;
lastnote=-1;
defaults();
};
void Part::defaults(){
Penabled=0;
Pminkey=0;
Pmaxkey=127;
Pnoteon=1;
Ppolymode=1;
setPvolume(96);
Pkeyshift=64;
Prcvchn=0;
setPpanning(64);
Pvelsns=64;
Pveloffs=64;
Pkeylimit=15;
defaultsinstrument();
ctl.defaults();
};
void Part::defaultsinstrument(){
ZERO(Pname,PART_MAX_NAME_LEN);
info.Ptype=0;
ZERO(info.Pauthor,MAX_INFO_TEXT_SIZE+1);
ZERO(info.Pcomments,MAX_INFO_TEXT_SIZE+1);
Pkitmode=0;
Pdrummode=0;
for (int n=0;n<NUM_KIT_ITEMS;n++){
kit[n].Penabled=0;kit[n].Pmuted=0;
kit[n].Pminkey=0;kit[n].Pmaxkey=127;
kit[n].Padenabled=0;kit[n].Psubenabled=0;kit[n].Ppadenabled=0;
ZERO(kit[n].Pname,PART_MAX_NAME_LEN);
kit[n].Psendtoparteffect=0;
if (n!=0) setkititemstatus(n,0);
};
kit[0].Penabled=1;
kit[0].Padenabled=1;
kit[0].adpars->defaults();
kit[0].subpars->defaults();
kit[0].padpars->defaults();
for (int nefx=0;nefx<NUM_PART_EFX;nefx++) {
partefx[nefx]->defaults();
Pefxroute[nefx]=0;//route to next effect
};
};
/*
* Cleanup the part
*/
void Part::cleanup(){
for (int k=0;k<POLIPHONY;k++) KillNotePos(k);
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
partoutl[i]=denormalkillbuf[i];
partoutr[i]=denormalkillbuf[i];
tmpoutl[i]=0.0;
tmpoutr[i]=0.0;
};
ctl.resetall();
for (int nefx=0;nefx<NUM_PART_EFX;nefx++) partefx[nefx]->cleanup();
for (int n=0;n<NUM_PART_EFX+1;n++) {
for (int i=0;i<SOUND_BUFFER_SIZE;i++){
partfxinputl[n][i]=denormalkillbuf[i];
partfxinputr[n][i]=denormalkillbuf[i];
};
};
};
Part::~Part(){
cleanup();
for (int n=0;n<NUM_KIT_ITEMS;n++){
if (kit[n].adpars!=NULL) delete (kit[n].adpars);
if (kit[n].subpars!=NULL) delete (kit[n].subpars);
if (kit[n].padpars!=NULL) delete (kit[n].padpars);
kit[n].adpars=NULL;kit[n].subpars=NULL;kit[n].padpars=NULL;
delete(kit[n].Pname);
};
delete (Pname);
delete (partoutl);
delete (partoutr);
delete (tmpoutl);
delete (tmpoutr);
for (int nefx=0;nefx<NUM_PART_EFX;nefx++)
delete (partefx[nefx]);
for (int n=0;n<NUM_PART_EFX+1;n++) {
delete (partfxinputl[n]);
delete (partfxinputr[n]);
};
};
/*
* Note On Messages
*/
void Part::NoteOn(unsigned char note,unsigned char velocity,int masterkeyshift){
int i,pos;
lastnote=note;
if ((note<Pminkey)||(note>Pmaxkey)) return;
pos=-1;
for (i=0;i<POLIPHONY;i++){
if (partnote[i].status==KEY_OFF){
pos=i;
break;
};
};
if (Ppolymode==0){//if the mode is 'mono' turn off all other notes
for (i=0;i<POLIPHONY;i++)
if (partnote[i].status==KEY_PLAYING) NoteOff(partnote[i].note);
RelaseSustainedKeys();
};
if (pos==-1){
//test
fprintf(stderr,"%s","NOTES TOO MANY (> POLIPHONY) - (Part.C::NoteOn(..))\n");
} else {
if (Pnoteon!=0){
//start the note
partnote[pos].status=KEY_PLAYING;
partnote[pos].note=note;
//this computes the velocity sensing of the part
REALTYPE vel=VelF(velocity/127.0,Pvelsns);
//compute the velocity offset
vel+=(Pveloffs-64.0)/64.0;
if (vel<0.0) vel=0.0; else if (vel>1.0) vel=1.0;
//compute the keyshift
int partkeyshift=(int)Pkeyshift-64;
int keyshift=masterkeyshift+partkeyshift;
//initialise note frequency
REALTYPE notebasefreq;
if (Pdrummode==0){
notebasefreq=microtonal->getnotefreq(note,keyshift);
if (notebasefreq<0.0) return;//the key is no mapped
} else {
notebasefreq=440.0*pow(2.0,(note-69.0)/12.0);
};
//Portamento
if (oldfreq<1.0) oldfreq=notebasefreq;//this is only the first note is played
int portamento=ctl.initportamento(oldfreq,notebasefreq);
if (portamento!=0) ctl.portamento.noteusing=pos;
oldfreq=notebasefreq;
partnote[pos].itemsplaying=0;
if (Pkitmode==0){//init the notes for the "normal mode"
partnote[pos].kititem[0].sendtoparteffect=0;
if (kit[0].Padenabled!=0) partnote[pos].kititem[0].adnote=new ADnote(kit[0].adpars,&ctl,notebasefreq,vel,portamento,note);
if (kit[0].Psubenabled!=0) partnote[pos].kititem[0].subnote=new SUBnote(kit[0].subpars,&ctl,notebasefreq,vel,portamento,note);
if (kit[0].Ppadenabled!=0) partnote[pos].kititem[0].padnote=new PADnote(kit[0].padpars,&ctl,notebasefreq,vel,portamento,note);
if ((kit[0].Padenabled!=0)||(kit[0].Psubenabled!=0)||(kit[0].Ppadenabled!=0)) partnote[pos].itemsplaying++;
} else {//init the notes for the "kit mode"
for (int item=0;item<NUM_KIT_ITEMS;item++){
if (kit[item].Pmuted!=0) continue;
if ((note<kit[item].Pminkey)||(note>kit[item].Pmaxkey)) continue;
int ci=partnote[pos].itemsplaying;//ci=current item
partnote[pos].kititem[ci].sendtoparteffect=( kit[item].Psendtoparteffect<NUM_PART_EFX ?
kit[item].Psendtoparteffect: NUM_PART_EFX);//if this parameter is 127 for "unprocessed"
if ((kit[item].adpars!=NULL)&&(kit[item].Padenabled)!=0)
partnote[pos].kititem[ci].adnote=new ADnote(kit[item].adpars,&ctl,notebasefreq,vel,portamento,note);
if ((kit[item].subpars!=NULL)&&(kit[item].Psubenabled)!=0)
partnote[pos].kititem[ci].subnote=new SUBnote(kit[item].subpars,&ctl,notebasefreq,vel,portamento,note);
if ((kit[item].padpars!=NULL)&&(kit[item].Ppadenabled)!=0)
partnote[pos].kititem[ci].padnote=new PADnote(kit[item].padpars,&ctl,notebasefreq,vel,portamento,note);
if ((kit[item].adpars!=NULL)|| (kit[item].subpars!=NULL)) {
partnote[pos].itemsplaying++;
if ( ((kit[item].Padenabled!=0)||(kit[item].Psubenabled!=0)||(kit[item].Ppadenabled!=0))
&& (Pkitmode==2) ) break;
};
};
};
};
};
//this only relase the keys if there is maximum number of keys allowed
setkeylimit(Pkeylimit);
};
/*
* Note Off Messages
*/
void Part::NoteOff(unsigned char note){//relase the key
int i;
for (i=POLIPHONY-1;i>=0;i--){ //first note in, is first out if there are same note multiple times
if ((partnote[i].status==KEY_PLAYING)&&(partnote[i].note==note)) {
if (ctl.sustain.sustain==0){ //the sustain pedal is not pushed
RelaseNotePos(i);
break;
} else {//the sustain pedal is pushed
partnote[i].status=KEY_RELASED_AND_SUSTAINED;
};
};
};
};
/*
* Controllers
*/
void Part::SetController(unsigned int type,int par){
switch (type){
case C_pitchwheel:ctl.setpitchwheel(par);
break;
case C_expression:ctl.setexpression(par);
setPvolume(Pvolume);//update the volume
break;
case C_portamento:ctl.setportamento(par);
break;
case C_panning:ctl.setpanning(par);
setPpanning(Ppanning);//update the panning
break;
case C_filtercutoff:ctl.setfiltercutoff(par);
break;
case C_filterq:ctl.setfilterq(par);
break;
case C_bandwidth:ctl.setbandwidth(par);
break;
case C_modwheel:ctl.setmodwheel(par);
break;
case C_fmamp:ctl.setfmamp(par);
break;
case C_volume:ctl.setvolume(par);
if (ctl.volume.receive!=0) volume=ctl.volume.volume;
else setPvolume(Pvolume);
break;
case C_sustain:ctl.setsustain(par);
if (ctl.sustain.sustain==0) RelaseSustainedKeys();
break;
case C_allsoundsoff:AllNotesOff();//Panic
break;
case C_resetallcontrollers:
ctl.resetall();
RelaseSustainedKeys();
if (ctl.volume.receive!=0) volume=ctl.volume.volume;
else setPvolume(Pvolume);
setPvolume(Pvolume);//update the volume
setPpanning(Ppanning);//update the panning
for (int item=0;item<NUM_KIT_ITEMS;item++){
if (kit[item].adpars==NULL) continue;
kit[item].adpars->GlobalPar.Reson->
sendcontroller(C_resonance_center,1.0);
kit[item].adpars->GlobalPar.Reson->
sendcontroller(C_resonance_bandwidth,1.0);
};
//more update to add here if I add controllers
break;
case C_allnotesoff:RelaseAllKeys();
break;
case C_resonance_center:
ctl.setresonancecenter(par);
for (int item=0;item<NUM_KIT_ITEMS;item++){
if (kit[item].adpars==NULL) continue;
kit[item].adpars->GlobalPar.Reson->
sendcontroller(C_resonance_center,ctl.resonancecenter.relcenter);
};
break;
case C_resonance_bandwidth:
ctl.setresonancebw(par);
kit[0].adpars->GlobalPar.Reson->
sendcontroller(C_resonance_bandwidth,ctl.resonancebandwidth.relbw);
break;
};
};
/*
* Relase the sustained keys
*/
void Part::RelaseSustainedKeys(){
for (int i=0;i<POLIPHONY;i++)
if (partnote[i].status==KEY_RELASED_AND_SUSTAINED) RelaseNotePos(i);
};
/*
* Relase all keys
*/
void Part::RelaseAllKeys(){
for (int i=0;i<POLIPHONY;i++){
if ((partnote[i].status!=KEY_RELASED)&&
(partnote[i].status!=KEY_OFF)) //thanks to Frank Neumann
RelaseNotePos(i);
};
};
/*
* Release note at position
*/
void Part::RelaseNotePos(int pos){
for (int j=0;j<NUM_KIT_ITEMS;j++){
if (partnote[pos].kititem[j].adnote!=NULL)
if (partnote[pos].kititem[j].adnote)
partnote[pos].kititem[j].adnote->relasekey();
if (partnote[pos].kititem[j].subnote!=NULL)
if (partnote[pos].kititem[j].subnote!=NULL)
partnote[pos].kititem[j].subnote->relasekey();
if (partnote[pos].kititem[j].padnote!=NULL)
if (partnote[pos].kititem[j].padnote)
partnote[pos].kititem[j].padnote->relasekey();
};
partnote[pos].status=KEY_RELASED;
};
/*
* Kill note at position
*/
void Part::KillNotePos(int pos){
partnote[pos].status=KEY_OFF;
partnote[pos].note=-1;
partnote[pos].time=0;
partnote[pos].itemsplaying=0;
for (int j=0;j<NUM_KIT_ITEMS;j++){
if (partnote[pos].kititem[j].adnote!=NULL) {
delete(partnote[pos].kititem[j].adnote);
partnote[pos].kititem[j].adnote=NULL;
};
if (partnote[pos].kititem[j].subnote!=NULL) {
delete(partnote[pos].kititem[j].subnote);
partnote[pos].kititem[j].subnote=NULL;
};
if (partnote[pos].kititem[j].padnote!=NULL) {
delete(partnote[pos].kititem[j].padnote);
partnote[pos].kititem[j].padnote=NULL;
};
};
if (pos==ctl.portamento.noteusing) {
ctl.portamento.noteusing=-1;
ctl.portamento.used=0;
};
};
/*
* Set Part's key limit
*/
void Part::setkeylimit(unsigned char Pkeylimit){
this->Pkeylimit=Pkeylimit;
int keylimit=Pkeylimit;
if (keylimit==0) keylimit=POLIPHONY-5;
//release old keys if the number of notes>keylimit
if (Ppolymode!=0){
int notecount=0;
for (int i=0;i<POLIPHONY;i++){
if ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED))
notecount++;
};
int oldestnotepos=-1,maxtime=0;
if (notecount>keylimit){//find out the oldest note
for (int i=0;i<POLIPHONY;i++){
if ( ((partnote[i].status==KEY_PLAYING)||(partnote[i].status==KEY_RELASED_AND_SUSTAINED))
&& (partnote[i].time>maxtime)){
maxtime=partnote[i].time;
oldestnotepos=i;
};
};
};
if (oldestnotepos!=-1) RelaseNotePos(oldestnotepos);
};
};
/*
* Prepare all notes to be turned off
*/
void Part::AllNotesOff(){
killallnotes=1;
};
/*
* Compute Part samples and store them in the partoutl[] and partoutr[]
*/
void Part::ComputePartSmps(){
int i,k;
int noteplay;//0 if there is nothing activated
for (int nefx=0;nefx<NUM_PART_EFX+1;nefx++){
for (i=0;i<SOUND_BUFFER_SIZE;i++){
partfxinputl[nefx][i]=0.0;
partfxinputr[nefx][i]=0.0;
};
};
for (k=0;k<POLIPHONY;k++){
if (partnote[k].status==KEY_OFF) continue;
noteplay=0;
partnote[k].time++;
//get the sampledata of the note and kill it if it's finished
for (int item=0;item<partnote[k].itemsplaying;item++){
int sendcurrenttofx=partnote[k].kititem[item].sendtoparteffect;
ADnote *adnote=partnote[k].kititem[item].adnote;
SUBnote *subnote=partnote[k].kititem[item].subnote;
PADnote *padnote=partnote[k].kititem[item].padnote;
//get from the ADnote
if (adnote!=NULL) {
noteplay++;
if (adnote->ready!=0) adnote->noteout(&tmpoutl[0],&tmpoutr[0]);
else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;};
if (adnote->finished()!=0){
delete (adnote);
partnote[k].kititem[item].adnote=NULL;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the ADnote to part(mix)
partfxinputl[sendcurrenttofx][i]+=tmpoutl[i];
partfxinputr[sendcurrenttofx][i]+=tmpoutr[i];
};
};
//get from the SUBnote
if (subnote!=NULL) {
noteplay++;
if (subnote->ready!=0) subnote->noteout(&tmpoutl[0],&tmpoutr[0]);
else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;};
for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the SUBnote to part(mix)
partfxinputl[sendcurrenttofx][i]+=tmpoutl[i];
partfxinputr[sendcurrenttofx][i]+=tmpoutr[i];
};
if (subnote->finished()!=0){
delete (subnote);
partnote[k].kititem[item].subnote=NULL;
};
};
//get from the PADnote
if (padnote!=NULL) {
noteplay++;
if (padnote->ready!=0) padnote->noteout(&tmpoutl[0],&tmpoutr[0]);
else for (i=0;i<SOUND_BUFFER_SIZE;i++){tmpoutl[i]=0.0;tmpoutr[i]=0.0;};
if (padnote->finished()!=0){
delete (padnote);
partnote[k].kititem[item].padnote=NULL;
};
for (i=0;i<SOUND_BUFFER_SIZE;i++){//add the PADnote to part(mix)
partfxinputl[sendcurrenttofx][i]+=tmpoutl[i];
partfxinputr[sendcurrenttofx][i]+=tmpoutr[i];
};
};
};
//Kill note if there is no synth on that note
if (noteplay==0) KillNotePos(k);
};
//Apply part's effects and mix them
for (int nefx=0;nefx<NUM_PART_EFX;nefx++) {
if (!Pefxbypass[nefx]) {
partefx[nefx]->out(partfxinputl[nefx],partfxinputr[nefx]);
if (Pefxroute[nefx]==2){
for (i=0;i<SOUND_BUFFER_SIZE;i++){
partfxinputl[nefx+1][i]+=partefx[nefx]->efxoutl[i];
partfxinputr[nefx+1][i]+=partefx[nefx]->efxoutr[i];
};
};
};
int routeto=((Pefxroute[nefx]==0) ? nefx+1 : NUM_PART_EFX);
for (i=0;i<SOUND_BUFFER_SIZE;i++){
partfxinputl[routeto][i]+=partfxinputl[nefx][i];
partfxinputr[routeto][i]+=partfxinputr[nefx][i];
};
};
for (i=0;i<SOUND_BUFFER_SIZE;i++){
partoutl[i]=partfxinputl[NUM_PART_EFX][i];
partoutr[i]=partfxinputr[NUM_PART_EFX][i];
};
//Kill All Notes if killallnotes!=0
if (killallnotes!=0) {
for (i=0;i<SOUND_BUFFER_SIZE;i++) {
REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE;
partoutl[i]*=tmp;
partoutr[i]*=tmp;
tmpoutl[i]=0.0;
tmpoutr[i]=0.0;
};
for (int k=0;k<POLIPHONY;k++) KillNotePos(k);
killallnotes=0;
for (int nefx=0;nefx<NUM_PART_EFX;nefx++) {
partefx[nefx]->cleanup();
};
};
ctl.updateportamento();
};
/*
* Parameter control
*/
void Part::setPvolume(char Pvolume_){
Pvolume=Pvolume_;
volume=dB2rap((Pvolume-96.0)/96.0*40.0)*ctl.expression.relvolume;
};
void Part::setPpanning(char Ppanning_){
Ppanning=Ppanning_;
panning=Ppanning/127.0+ctl.panning.pan;
if (panning<0.0) panning=0.0;else if (panning>1.0) panning=1.0;
};
/*
* Enable or disable a kit item
*/
void Part::setkititemstatus(int kititem,int Penabled_){
if ((kititem==0)&&(kititem>=NUM_KIT_ITEMS)) return;//nonexistent kit item and the first kit item is always enabled
kit[kititem].Penabled=Penabled_;
bool resetallnotes=false;
if (Penabled_==0){
if (kit[kititem].adpars!=NULL) delete (kit[kititem].adpars);
if (kit[kititem].subpars!=NULL) delete (kit[kititem].subpars);
if (kit[kititem].padpars!=NULL) {
delete (kit[kititem].padpars);
resetallnotes=true;
};
kit[kititem].adpars=NULL;kit[kititem].subpars=NULL;kit[kititem].padpars=NULL;
kit[kititem].Pname[0]='\0';
} else {
if (kit[kititem].adpars==NULL) kit[kititem].adpars=new ADnoteParameters(fft);
if (kit[kititem].subpars==NULL) kit[kititem].subpars=new SUBnoteParameters();
if (kit[kititem].padpars==NULL) kit[kititem].padpars=new PADnoteParameters(fft,mutex);
};
if (resetallnotes) for (int k=0;k<POLIPHONY;k++) KillNotePos(k);
};
void Part::add2XMLinstrument(XMLwrapper *xml){
xml->beginbranch("INFO");
xml->addparstr("name",(char *)Pname);
xml->addparstr("author",(char *)info.Pauthor);
xml->addparstr("comments",(char *)info.Pcomments);
xml->addpar("type",info.Ptype);
xml->endbranch();
xml->beginbranch("INSTRUMENT_KIT");
xml->addpar("kit_mode",Pkitmode);
xml->addparbool("drum_mode",Pdrummode);
for (int i=0;i<NUM_KIT_ITEMS;i++){
xml->beginbranch("INSTRUMENT_KIT_ITEM",i);
xml->addparbool("enabled",kit[i].Penabled);
if (kit[i].Penabled!=0) {
xml->addparstr("name",(char *)kit[i].Pname);
xml->addparbool("muted",kit[i].Pmuted);
xml->addpar("min_key",kit[i].Pminkey);
xml->addpar("max_key",kit[i].Pmaxkey);
xml->addpar("send_to_instrument_effect",kit[i].Psendtoparteffect);
xml->addparbool("add_enabled",kit[i].Padenabled);
if ((kit[i].Padenabled!=0)&&(kit[i].adpars!=NULL)){
xml->beginbranch("ADD_SYNTH_PARAMETERS");
kit[i].adpars->add2XML(xml);
xml->endbranch();
};
xml->addparbool("sub_enabled",kit[i].Psubenabled);
if ((kit[i].Psubenabled!=0)&&(kit[i].subpars!=NULL)){
xml->beginbranch("SUB_SYNTH_PARAMETERS");
kit[i].subpars->add2XML(xml);
xml->endbranch();
};
xml->addparbool("pad_enabled",kit[i].Ppadenabled);
if ((kit[i].Ppadenabled!=0)&&(kit[i].padpars!=NULL)){
xml->beginbranch("PAD_SYNTH_PARAMETERS");
kit[i].padpars->add2XML(xml);
xml->endbranch();
};
};
xml->endbranch();
};
xml->endbranch();
xml->beginbranch("INSTRUMENT_EFFECTS");
for (int nefx=0;nefx<NUM_PART_EFX;nefx++){
xml->beginbranch("INSTRUMENT_EFFECT",nefx);
xml->beginbranch("EFFECT");
partefx[nefx]->add2XML(xml);
xml->endbranch();
xml->addpar("route",Pefxroute[nefx]);
partefx[nefx]->setdryonly(Pefxroute[nefx]==2);
xml->addparbool("bypass",Pefxbypass[nefx]);
xml->endbranch();
};
xml->endbranch();
};
void Part::add2XML(XMLwrapper *xml){
//parameters
xml->addparbool("enabled",Penabled);
if ((Penabled==0)&&(xml->minimal)) return;
xml->addpar("volume",Pvolume);
xml->addpar("panning",Ppanning);
xml->addpar("min_key",Pminkey);
xml->addpar("max_key",Pmaxkey);
xml->addpar("key_shift",Pkeyshift);
xml->addpar("rcv_chn",Prcvchn);
xml->addpar("velocity_sensing",Pvelsns);
xml->addpar("velocity_offset",Pveloffs);
xml->addparbool("note_on",Pnoteon);
xml->addparbool("poly_mode",Ppolymode);
xml->addpar("key_limit",Pkeylimit);
xml->beginbranch("INSTRUMENT");
add2XMLinstrument(xml);
xml->endbranch();
xml->beginbranch("CONTROLLER");
ctl.add2XML(xml);
xml->endbranch();
};
int Part::saveXML(char *filename){
XMLwrapper *xml;
xml=new XMLwrapper();
xml->beginbranch("INSTRUMENT");
add2XMLinstrument(xml);
xml->endbranch();
int result=xml->saveXMLfile(filename);
delete (xml);
return(result);
};
int Part::loadXMLinstrument(const char *filename){
XMLwrapper *xml=new XMLwrapper();
if (xml->loadXMLfile(filename)<0) {
delete(xml);
return(-1);
};
if (xml->enterbranch("INSTRUMENT")==0) return(-10);
getfromXMLinstrument(xml);
xml->exitbranch();
delete(xml);
return(0);
};
void Part::applyparameters(){
for (int n=0;n<NUM_KIT_ITEMS;n++){
if ((kit[n].padpars!=NULL)&&(kit[n].Ppadenabled!=0)) kit[n].padpars->applyparameters(true);
};
};
void Part::getfromXMLinstrument(XMLwrapper *xml){
if (xml->enterbranch("INFO")){
xml->getparstr("name",(char *)Pname,PART_MAX_NAME_LEN);
xml->getparstr("author",(char *)info.Pauthor,MAX_INFO_TEXT_SIZE);
xml->getparstr("comments",(char *)info.Pcomments,MAX_INFO_TEXT_SIZE);
info.Ptype=xml->getpar("type",info.Ptype,0,16);
xml->exitbranch();
};
if (xml->enterbranch("INSTRUMENT_KIT")){
Pkitmode=xml->getpar127("kit_mode",Pkitmode);
Pdrummode=xml->getparbool("drum_mode",Pdrummode);
setkititemstatus(0,0);
for (int i=0;i<NUM_KIT_ITEMS;i++){
if (xml->enterbranch("INSTRUMENT_KIT_ITEM",i)==0) continue;
setkititemstatus(i,xml->getparbool("enabled",kit[i].Penabled));
if (kit[i].Penabled==0) {
xml->exitbranch();
continue;
};
xml->getparstr("name",(char *)kit[i].Pname,PART_MAX_NAME_LEN);
kit[i].Pmuted=xml->getparbool("muted",kit[i].Pmuted);
kit[i].Pminkey=xml->getpar127("min_key",kit[i].Pminkey);
kit[i].Pmaxkey=xml->getpar127("max_key",kit[i].Pmaxkey);
kit[i].Psendtoparteffect=xml->getpar127("send_to_instrument_effect",kit[i].Psendtoparteffect);
kit[i].Padenabled=xml->getparbool("add_enabled",kit[i].Padenabled);
if (xml->enterbranch("ADD_SYNTH_PARAMETERS")){
kit[i].adpars->getfromXML(xml);
xml->exitbranch();
};
kit[i].Psubenabled=xml->getparbool("sub_enabled",kit[i].Psubenabled);
if (xml->enterbranch("SUB_SYNTH_PARAMETERS")){
kit[i].subpars->getfromXML(xml);
xml->exitbranch();
};
kit[i].Ppadenabled=xml->getparbool("pad_enabled",kit[i].Ppadenabled);
if (xml->enterbranch("PAD_SYNTH_PARAMETERS")){
kit[i].padpars->getfromXML(xml);
xml->exitbranch();
};
xml->exitbranch();
};
xml->exitbranch();
};
if (xml->enterbranch("INSTRUMENT_EFFECTS")){
for (int nefx=0;nefx<NUM_PART_EFX;nefx++){
if (xml->enterbranch("INSTRUMENT_EFFECT",nefx)==0) continue;
if (xml->enterbranch("EFFECT")){
partefx[nefx]->getfromXML(xml);
xml->exitbranch();
};
Pefxroute[nefx]=xml->getpar("route",Pefxroute[nefx],0,NUM_PART_EFX);
partefx[nefx]->setdryonly(Pefxroute[nefx]==2);
Pefxbypass[nefx]=xml->getparbool("bypass",Pefxbypass[nefx]);
xml->exitbranch();
};
xml->exitbranch();
};
};
void Part::getfromXML(XMLwrapper *xml){
Penabled=xml->getparbool("enabled",Penabled);
setPvolume(xml->getpar127("volume",Pvolume));
setPpanning(xml->getpar127("panning",Ppanning));
Pminkey=xml->getpar127("min_key",Pminkey);
Pmaxkey=xml->getpar127("max_key",Pmaxkey);
Pkeyshift=xml->getpar127("key_shift",Pkeyshift);
Prcvchn=xml->getpar127("rcv_chn",Prcvchn);
Pvelsns=xml->getpar127("velocity_sensing",Pvelsns);
Pveloffs=xml->getpar127("velocity_offset",Pveloffs);
Pnoteon=xml->getparbool("note_on",Pnoteon);
Ppolymode=xml->getparbool("poly_mode",Ppolymode);
Pkeylimit=xml->getpar127("key_limit",Pkeylimit);
if (xml->enterbranch("INSTRUMENT")){
getfromXMLinstrument(xml);
xml->exitbranch();
};
if (xml->enterbranch("CONTROLLER")){
ctl.getfromXML(xml);
xml->exitbranch();
};
};